
#include "KLineWidget.h"
#include <QPainter>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QDebug>
#include <algorithm>
#include <QVector>
#include <QRandomGenerator>
#include <QDate>

KLineWidget::KLineWidget(QWidget *parent) : QWidget(parent),
    m_startIndex(0),
    m_displayCount(30),
    m_maxPrice(0),
    m_minPrice(0),
    m_hoveredIndex(-1),
    m_showCrosshair(false),
    m_marginLeft(60),
    m_marginRight(10),
    m_marginTop(10),
    m_marginBottom(30)
{
    // 初始化画笔和画刷
    m_upPen.setColor(Qt::red);
    m_upPen.setWidth(1);
    m_downPen.setColor(Qt::green);
    m_downPen.setWidth(1);
    m_upBrush.setColor(Qt::red);
    m_downBrush.setColor(Qt::green);
    m_axisPen.setColor(Qt::darkGray);
    m_axisPen.setWidth(1);
    m_gridPen.setColor(QColor(200, 200, 200));
    m_gridPen.setWidth(1);
    m_gridPen.setStyle(Qt::DashLine);
    m_crossPen.setColor(Qt::blue);
    m_crossPen.setWidth(1);
    m_crossPen.setStyle(Qt::DotLine);

    // 设置背景色
    setBackgroundRole(QPalette::Light);
    setAutoFillBackground(true);
}

void KLineWidget::setKLineData(const QVector<KLineData>& data)
{
    m_klineData = data;

    // 计算最大和最小价格
    if (!m_klineData.isEmpty()) {
        m_maxPrice = m_klineData[0].high;
        m_minPrice = m_klineData[0].low;

        for (const auto& kline : m_klineData) {
            m_maxPrice = qMax(m_maxPrice, kline.high);
            m_minPrice = qMin(m_minPrice, kline.low);
        }

        // 增加一些边距，使图形不贴边
        qreal margin = (m_maxPrice - m_minPrice) * 0.1;
        m_maxPrice += margin;
        m_minPrice -= margin;
    }

    // 确保显示范围有效
    m_startIndex = 0;
    m_displayCount = qMin(30, m_klineData.size());

    update();
}

void KLineWidget::setViewRange(int start, int count)
{
    if (start < 0) start = 0;
    if (start + count > m_klineData.size()) {
        start = qMax(0, (int)m_klineData.size() - count);
    }

    m_startIndex = start;
    m_displayCount = count;
    update();
}

void KLineWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 绘制坐标轴和网格
    drawAxes(painter);

    // 绘制K线
    if (!m_klineData.isEmpty()) {
        drawKLines(painter);
    }

    // 绘制十字光标
    if (m_showCrosshair && m_hoveredIndex >= 0 &&
        m_hoveredIndex < m_klineData.size()) {
        drawCrosshair(painter);
    }
}

void KLineWidget::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
    update();
}

void KLineWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_showCrosshair = true;
        m_hoveredIndex = xToIndex(event->x());
        update();
    }
    QWidget::mousePressEvent(event);
}

void KLineWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (m_showCrosshair) {
        m_hoveredIndex = xToIndex(event->x());
        update();
    }
    QWidget::mouseMoveEvent(event);
}

void KLineWidget::wheelEvent(QWheelEvent *event)
{
    // 鼠标滚轮缩放
    int delta = event->angleDelta().y();
    if (delta > 0) {
        // 放大
        m_displayCount = qMax(10, m_displayCount - 5);
    } else {
        // 缩小
        m_displayCount = qMin((int)m_klineData.size(), m_displayCount + 5);
    }

    setViewRange(m_startIndex, m_displayCount);
    QWidget::wheelEvent(event);
}

void KLineWidget::drawKLines(QPainter& painter)
{
    int graphWidth = width() - m_marginLeft - m_marginRight;
    int graphHeight = height() - m_marginTop - m_marginBottom;

    if (graphWidth <= 0 || graphHeight <= 0) return;

    // 计算K线宽度
    int klineWidth = qMax(1, graphWidth / (m_displayCount * 2));
    if (klineWidth > 10) klineWidth = 10; // 限制最大宽度

    // 绘制每一根K线
    for (int i = 0; i < m_displayCount; ++i) {
        int dataIndex = m_startIndex + i;
        if (dataIndex >= m_klineData.size()) break;

        const KLineData& kline = m_klineData[dataIndex];
        int x = m_marginLeft + i * graphWidth / m_displayCount + graphWidth / (m_displayCount * 2);

        // 绘制上下影线
        painter.setPen(kline.close >= kline.open ? m_upPen : m_downPen);
        int highY = priceToY(kline.high);
        int lowY = priceToY(kline.low);
        painter.drawLine(x, highY, x, lowY);

        // 绘制实体
        int openY = priceToY(kline.open);
        int closeY = priceToY(kline.close);

        painter.setPen(kline.close >= kline.open ? m_upPen : m_downPen);
        painter.setBrush(kline.close >= kline.open ? m_upBrush : m_downBrush);

        if (openY > closeY) {
            painter.drawRect(x - klineWidth / 2, closeY, klineWidth, openY - closeY);
        } else if (closeY > openY) {
            painter.drawRect(x - klineWidth / 2, openY, klineWidth, closeY - openY);
        } else {
            // 开盘价等于收盘价，绘制一条横线
            painter.drawLine(x - klineWidth / 2, openY, x + klineWidth / 2, openY);
        }
    }
}

void KLineWidget::drawAxes(QPainter& painter)
{
    int graphWidth = width() - m_marginLeft - m_marginRight;
    int graphHeight = height() - m_marginTop - m_marginBottom;
    int graphX = m_marginLeft;
    int graphY = m_marginTop;

    // 绘制坐标轴
    painter.setPen(m_axisPen);
    painter.drawRect(graphX, graphY, graphWidth, graphHeight);

    // 绘制水平网格线和价格标签
    int hGridCount = 5;
    painter.setPen(m_gridPen);
    for (int i = 0; i <= hGridCount; ++i) {
        int y = graphY + i * graphHeight / hGridCount;
        painter.drawLine(graphX, y, graphX + graphWidth, y);

        // 绘制价格标签
        qreal price = m_maxPrice - (m_maxPrice - m_minPrice) * i / hGridCount;
        painter.drawText(graphX - m_marginLeft + 5, y + 5,
                         QString::number(price, 'f', 2));
    }

    // 绘制垂直网格线和日期标签
    int vGridCount = 5;
    for (int i = 0; i <= vGridCount; ++i) {
        int x = graphX + i * graphWidth / vGridCount;
        painter.drawLine(x, graphY, x, graphY + graphHeight);

        // 绘制日期标签
        int dataIndex = m_startIndex + i * m_displayCount / vGridCount;
        if (dataIndex < m_klineData.size()) {
            painter.drawText(x - 20, graphY + graphHeight + 20,
                             m_klineData[dataIndex].date);
        }
    }
}

void KLineWidget::drawCrosshair(QPainter& painter)
{
    if (m_hoveredIndex < 0 || m_hoveredIndex >= m_klineData.size()) return;

    int graphWidth = width() - m_marginLeft - m_marginRight;
    int graphHeight = height() - m_marginTop - m_marginBottom;
    int graphX = m_marginLeft;
    int graphY = m_marginTop;

    const KLineData& kline = m_klineData[m_hoveredIndex];
    int x = indexToX(m_hoveredIndex - m_startIndex);

    // 绘制十字线
    painter.setPen(m_crossPen);
    painter.drawLine(x, graphY, x, graphY + graphHeight);

    // 绘制数据提示框
    QString info = QString("日期: %1\n开盘: %2\n最高: %3\n最低: %4\n收盘: %5")
                       .arg(kline.date)
                       .arg(kline.open)
                       .arg(kline.high)
                       .arg(kline.low)
                       .arg(kline.close);

    QRect textRect(x + 10, graphY + 10, 150, 100);
    painter.fillRect(textRect, QColor(255, 255, 255, 200));
    painter.setPen(Qt::black);
    painter.drawText(textRect, Qt::TextWordWrap, info);
    painter.drawRect(textRect);
}

int KLineWidget::priceToY(qreal price) const
{
    if (m_maxPrice <= m_minPrice) return m_marginTop;

    int graphHeight = height() - m_marginTop - m_marginBottom;
    return m_marginTop + graphHeight * (1 - (price - m_minPrice) / (m_maxPrice - m_minPrice));
}

int KLineWidget::xToIndex(int x) const
{
    int graphWidth = width() - m_marginLeft - m_marginRight;
    if (graphWidth <= 0) return -1;

    if (x < m_marginLeft) return m_startIndex;
    if (x > width() - m_marginRight) return m_startIndex + m_displayCount - 1;

    int relativeX = x - m_marginLeft;
    int indexInDisplay = (relativeX * m_displayCount) / graphWidth;
    return m_startIndex + indexInDisplay;
}

int KLineWidget::indexToX(int index) const
{
    int graphWidth = width() - m_marginLeft - m_marginRight;
    if (graphWidth <= 0) return m_marginLeft;

    return m_marginLeft + index * graphWidth / m_displayCount + graphWidth / (m_displayCount * 2);
}

// 生成随机K线数据用于测试
QVector<KLineData> generateRandomKLineData(int count)
{
    QVector<KLineData> data;
    qreal price = 100.0; // 初始价格

    QDate date = QDate::currentDate().addDays(-count);

    for (int i = 0; i < count; ++i) {
        KLineData kline;

        // 随机生成价格变化
        qreal change = QRandomGenerator::global()->bounded(4.0) - 2.0; // -2 到 2 之间的随机数
        price += change;

        // 生成开盘价、收盘价、最高价、最低价
        kline.open = price;
        kline.close = price + (QRandomGenerator::global()->bounded(3.0) - 1.5);
        kline.high = qMax(kline.open, kline.close) + QRandomGenerator::global()->bounded(2.0);
        kline.low = qMin(kline.open, kline.close) - QRandomGenerator::global()->bounded(2.0);
        kline.date = date.addDays(i).toString("MM-dd");

        data.append(kline);
    }

    return data;
}
void testKline(){

    // 创建K线部件
    KLineWidget klineWidget;

    // 生成并设置K线数据
    QVector<KLineData> data = generateRandomKLineData(100);
    klineWidget.setKLineData(data);

    // 设置窗口属性
    klineWidget.setWindowTitle("K线图示例");
    klineWidget.resize(1000, 600);
    klineWidget.show();
}
